home *** CD-ROM | disk | FTP | other *** search
/ The Atari Compendium / The Atari Compendium (Toad Computers) (1994).iso / files / prgtools / programm.ing / ltmf_120.lzh / LTMF_DO.C < prev    next >
Encoding:
C/C++ Source or Header  |  1993-04-26  |  24.0 KB  |  1,037 lines

  1. /* ------------------------------------------------------------------------- */
  2. /* ----- Let 'em Fly!   V 1.2 ----------- (c) 1991-93 by Oliver Scheel ----- */
  3. /* ------------------------------------------------------------------------- */
  4. /* ----- Module: ltmf_do.c   new form_do() --------------------------------- */
  5. /* ------------------------------------------------------------------------- */
  6.  
  7. #include <stdio.h>
  8. #include <stdlib.h>
  9. #include <string.h>
  10. #include <ctype.h>
  11. #include <tos.h>
  12. #include <smallaes.h>
  13. #include <vdi.h>
  14. #include <magx_old.h>
  15. #include <portab.h>
  16.  
  17. #include "letemfly.h"
  18. #include "ltmf_str.h"
  19. #include "ltmf_def.h"
  20.  
  21. /* ------------------------------------------------------------------------- */
  22.  
  23. EXTERN    WORD    global[];
  24.  
  25. EXTERN    WORD    vwk_handle,
  26.         colors,
  27.         sysfont;
  28.  
  29. EXTERN    WORD    gl_wchar,
  30.         gl_hchar;
  31. EXTERN    GRECT    wi_max;
  32. EXTERN    WORD    ind_mode,
  33.         act_mode;
  34.  
  35. EXTERN    OBJECT    *lasttree;
  36.  
  37. EXTERN    OBJECT    *info_dial,
  38.         *char_dial;
  39.  
  40. EXTERN    WORD    magic;
  41. EXTERN    WORD    isalert;
  42. EXTERN    WORD    initflag;
  43. EXTERN    WORD    jacks_in;
  44. EXTERN    WORD    was_used;
  45.  
  46. EXTERN    MAGX_COOKIE    *magx;
  47.  
  48. /* ------------------------------------------------------------------------- */
  49.  
  50. WORD vwk_init    _((VOID));
  51. VOID vwk_exit    _((WORD handle));
  52. VOID obj_xywh    _((OBJECT *tree, WORD obj, GRECT *p));
  53. VOID obj_update    _((OBJECT *tree, WORD obj));
  54. VOID STDARGS obj_clsize    _((OBJECT *tree, WORD obj, WORD *x, WORD *y, WORD *w, WORD *h));
  55. VOID rc_gtov    _((GRECT *src, VRECT *dest));
  56. VOID rc_vtog    _((VRECT *src, GRECT *dest));
  57. WORD ltmf_init    _((VOID));
  58.  
  59. WORD nfm_do    _((OBJECT *tree, WORD startobj));
  60. WORD nfm_dial    _((WORD flag, WORD xs, WORD ys, WORD ws, WORD hs, WORD x, WORD y, WORD w, WORD h));
  61. WORD nfm_center    _((OBJECT *tree, WORD *x, WORD *y, WORD *w, WORD *h));
  62. WORD nfm_button    _((OBJECT *tree, WORD obj, WORD clicks, WORD *nxtobj));
  63. WORD nfm_keybd    _((OBJECT *tree, WORD obj, WORD next_obj, WORD thechar, WORD *pnxt_obj, WORD *pchar));
  64. WORD nob_edit    _((OBJECT *tree, WORD obj, WORD thechar, WORD *idx, WORD kind));
  65. VOID STDARGS di_fly    _((OBJECT *tree));
  66. WORD STDARGS di_moveto    _((OBJECT *tree, WORD x, WORD y));
  67. WORD STDARGS di_center    _((OBJECT *tree));
  68.  
  69. CHAR STDARGS ins_spcchar    _((VOID));
  70. WORD STDARGS lookup_key    _((WORD key, WORD status));
  71. WORD STDARGS init_keys    _((OBJECT *tree ));
  72.  
  73. MLOCAL WORD _conv_ch    _((CHAR ch));
  74. MLOCAL VOID _dialval    _((WORD mode));
  75. MLOCAL CHAR *_get_text    _((OBJECT *tree, WORD obj, CHAR **txtptr, WORD *tlen));
  76. MLOCAL WORD _is_spec    _((ALIAS *list, WORD num, CHAR *text));
  77. MLOCAL WORD _inskeytab    _((WORD pos , WORD obj , WORD keyobj , WORD cpos , WORD tlen ));
  78. MLOCAL VOID _ins_key    _((OBJECT *tree, WORD obj, WORD in));
  79. MLOCAL VOID _und_key    _((OBJECT *tree, KBDTAB *ktab, WORD obj, WORD mode));
  80. MLOCAL WORD _find_kobj    _((OBJECT *tree, WORD obj));
  81. MLOCAL WORD _getcpos    _((OBJECT *tree, WORD obj, WORD x));
  82. MLOCAL VOID _tw        _((OBJECT *tree, WORD start));
  83. MLOCAL WORD _init_fm    _((OBJECT *tree, WORD startobj));
  84.  
  85. VOID _und_obj    _((OBJECT *tree, KBDTAB *ktab, WORD obj, WORD mode));
  86.  
  87. /* ------------------------------------------------------------------------- */
  88.  
  89. KBDTAB    keytable[MAXKEYS],
  90.     oldkbtab[MAXKEYS];
  91.  
  92. WORD    undo_obj;
  93. WORD    help_obj;
  94. WORD    fly_obj;
  95.  
  96. ALIAS    undos[MAXUNDO] = {    "abbruch",    7,
  97.                 "abbrechen",    9,
  98.                 "verlassen",    9,
  99.                 "nein",        4,
  100.                 "ende",        4,
  101.                 "quit",        4,
  102.                 "cancel",    6,
  103.                 "abort",    5,
  104.                 "no",        2,
  105.                 "exit",        4 };
  106.  
  107. ALIAS    helps[MAXHELP] = {    "help",        4,
  108.                 "hilfe",    5 };
  109.  
  110. /*
  111. ALIAS    oks[MAXOK] = {        "ok",        2,
  112.                 "ja",        2,
  113.                 "yes",        3 };
  114. */
  115.  
  116. CHAR    txtbuf[2];        /* small text buffer    */
  117.  
  118. WORD    keys;            /* key dials available    */
  119. WORD    in_do = 0;        /* form_do ist active    */
  120. WORD    ed_flag = 0;        /* no EDITABLE        */
  121.  
  122. OBJECT    *lastdone = NULL;
  123.  
  124. /* ------------------------------------------------------------------------- */
  125. /* ----- utilities --------------------------------------------------------- */
  126. /* ------------------------------------------------------------------------- */
  127.  
  128. /* ----- convert char to pos ----------------------------------------------- */
  129.  
  130. MLOCAL WORD _conv_ch(ch)
  131. CHAR    ch;
  132. {
  133.     ch = toupper(ch);
  134.     if(isdigit(ch))
  135.         ch -= 48;
  136.     else if(isalpha(ch))
  137.         ch -= 55;
  138.     else
  139.         ch = -1;
  140.     return(ch);
  141. }
  142.  
  143. /* ----- save/restore dialog values ---------------------------------------- */
  144.  
  145. MLOCAL VOID _dialval(mode)
  146. WORD    mode;
  147. {
  148.     static WORD    ksav, jsav, fsav, wusav;
  149.     static OBJECT    *tsav;
  150. /*    static MFORM    mf_sav;
  151. */
  152.     if(mode == DSAVE)
  153.     {
  154.         ksav = keys;        /* save special values */
  155.         fsav = fly_obj;
  156.         tsav = lastdone;
  157.         jsav = jacks_in;
  158.         wusav = was_used;
  159.         jacks_in = 1;
  160. /*        memcpy(&mf_sav, &mf, sizeof(MFORM));
  161. */    }
  162.     else
  163.     {
  164.         keys = ksav;        /* restore values */
  165.         fly_obj = fsav;
  166.         lastdone = tsav;
  167.         jacks_in = jsav;
  168.         was_used = wusav;
  169. /*        memcpy(&mf, &mf_sav, sizeof(MFORM));
  170. */    }
  171. }
  172.  
  173. /* ----- insert special character ------------------------------------------ */
  174.  
  175. CHAR STDARGS ins_spcchar()
  176. {
  177.     WORD    x, y, w, h;
  178.     WORD    choice, d;
  179.     CHAR    ch;
  180.     GRECT    gr;
  181.  
  182.     isalert = TRUE;
  183.     _dialval(DSAVE);
  184.     nfm_center(char_dial, &x, &y, &w, &h);
  185.     nfm_dial(FMD_START, 0, 0, 0, 0, x, y, w, h);
  186.     objc_draw(char_dial, ROOT, MAX_DEPTH, x, y, w, h);
  187.     choice = nfm_do(char_dial, 0) & 0x7fff;
  188.     nfm_dial(FMD_FINISH, 0, 0, 0, 0, x, y, w, h);
  189.     char_dial[choice].ob_state &= ~SELECTED;
  190.     _dialval(DRESTORE);
  191.     isalert = FALSE;
  192.     if(choice != CHARCANC)
  193.     {
  194.         graf_mkstate(&x, &y, &d, &d);
  195.         evnt_button(1, 1, 0, &d, &d, &d, &d);
  196.         obj_xywh(char_dial, choice, &gr);
  197.         x = (x - gr.g_x) / gl_wchar;
  198.         choice = (choice - CHARTXT0) * 32 + x;
  199.         if(choice == 0)
  200.             ch = 127;
  201.         else if(choice < 32)
  202.             ch = choice;
  203.         else
  204.             ch = choice - 160;
  205.         return(ch);
  206.     }
  207.     return(0);
  208. }
  209.  
  210. /* ----- get text from object ---------------------------------------------- */
  211.  
  212. MLOCAL CHAR *_get_text(tree, obj, txtptr, tlen)
  213. OBJECT    *tree;
  214. WORD    obj;
  215. CHAR    **txtptr;
  216. WORD    *tlen;
  217. {
  218.     WORD    typ;
  219.     CHAR    *txtp;
  220.     OBJECT    *tr;
  221.     OBSPEC    *obspc;
  222.  
  223.     tr = &tree[obj];
  224.     typ = tr->ob_type & 0xff;
  225.     if(magic && (typ == G_USERDEF) && (tr->ob_type & EXAPPL))
  226.     {
  227.         typ = tr->ob_spec.exapblk->ub_type & 0xff;
  228.         obspc = &tr->ob_spec.exapblk->ub_spec;
  229.     }
  230.     else
  231.         obspc = (tr->ob_flags & INDIRECT) ? &tr->ob_spec.indirect : &tr->ob_spec;
  232.     if((typ == G_TEXT) || (typ == G_BOXTEXT))
  233.         txtp = obspc->tedinfo->te_ptext;
  234.     else if((typ == G_FTEXT) || (typ == G_FBOXTEXT))
  235.         txtp = obspc->tedinfo->te_ptmplt;
  236.     else if(typ == G_BOXCHAR)
  237.     {
  238.         txtbuf[0] = obspc->obspec.character;
  239.         txtbuf[1] = 0;
  240.         txtp = txtbuf;
  241.     }
  242.     else if((typ == G_BUTTON) || (typ == G_STRING))
  243.         txtp = obspc->free_string;
  244.     else
  245.         txtp = strcpy(txtbuf, "");
  246.     if(tlen != NULL)
  247.         *tlen = (WORD)strlen(txtp);
  248.     if(txtptr != NULL)
  249.     {
  250.         *txtptr = txtp;
  251.         while(**txtptr && !isalnum(**txtptr))
  252.             (*txtptr)++;
  253.     }
  254.     return(txtp);
  255. }
  256.  
  257. MLOCAL WORD _is_spec(list, num, text)
  258. ALIAS    *list;
  259. WORD    num;
  260. CHAR    *text;
  261. {
  262.     REG WORD    i;
  263.  
  264.     for(i = 0; (i < num) && list[i].text; i++)
  265.     {
  266.         if(!strnicmp(text, list[i].text, list[i].len))
  267.             return(TRUE);
  268.     }
  269.     return(FALSE);
  270. }
  271.  
  272. MLOCAL WORD _inskeytab(pos, obj, keyobj, cpos, tlen)
  273. WORD    pos,
  274.     obj,
  275.     keyobj,
  276.     cpos,
  277.     tlen;
  278. {
  279.     KBDTAB    *kt;
  280.     WORD    savobj;
  281.  
  282.     kt = &keytable[pos];
  283.     savobj = kt->obj;
  284.     kt->obj = obj;
  285.     kt->kobj = keyobj;
  286.     kt->chpos = cpos;
  287.     kt->tlen = tlen;
  288.     return(savobj);
  289. }
  290.  
  291. /* ----- insert key into table --------------------------------------------- */
  292.  
  293. MLOCAL VOID _ins_key(tree, obj, in)
  294. OBJECT    *tree;
  295. WORD    obj,
  296.     in;
  297. {
  298.     REG WORD    i;
  299.     WORD    pos,
  300.         extype;
  301.     WORD    savobj,
  302.         keyobj,
  303.         priv,
  304.         tlen,
  305.         cpos;
  306.     CHAR    *txtp,
  307.         *txtp2;
  308.     KBDTAB    *kt;
  309.     OBJECT    *tr, *tr1;
  310.  
  311.     savobj = 0;
  312.     keyobj = obj;
  313.     priv = FALSE;
  314.     extype = tree[keyobj].ob_type & 0xff00;
  315.     cpos = ((extype & 0x0f00) >> 8) - 1;
  316.     if(magic && (extype & TKNEXT))
  317.         keyobj++;
  318.     if(magic && (extype & (0x0f00|SPECIAL)) && in)
  319.     {
  320.         if(extype & SPECIAL)
  321.         {
  322.             switch(cpos)
  323.             {
  324.                 case 0    :    undo_obj = obj;
  325.                     _ins_key(tree, obj, FALSE);
  326.                         break;
  327.                 case 1    :    help_obj = obj;
  328.                     _ins_key(tree, obj, FALSE);
  329.                         break;
  330.                 default   : kt = &keytable[cpos+MAXALPH-2];
  331.                         kt->obj = obj;
  332.                         kt->kobj = 0;
  333.                         goto norm_ins;
  334.             }
  335.         }
  336.         else
  337.         {
  338.             txtp = _get_text(tree, keyobj, &txtp2, &tlen);
  339.             pos = _conv_ch(txtp[cpos]);
  340.             if(pos == -1)
  341.                 goto leave;
  342.             savobj = _inskeytab(pos, obj, keyobj, cpos, tlen);
  343.             if(savobj)
  344.                 _ins_key(tree, savobj, FALSE);
  345.         }
  346.     }
  347.     else
  348.     {
  349. norm_ins:    txtp = _get_text(tree, keyobj, &txtp2, &tlen);
  350.         tr = &tree[obj];
  351.         if(magic && (tr->ob_flags & NODUPE))
  352.             goto leave;
  353.         if((tlen == 0) && !(tr->ob_flags & LASTOB))
  354.         {
  355.             tr1 = &tree[obj+1]; /* tr + sizeof(OBJECT); */
  356.             if(!(tr1->ob_flags & (SELECTABLE|TOUCHEXIT|EXIT|HIDETREE)) && !(tr1->ob_state & DISABLED))
  357.             {
  358.                 if(abs(tr1->ob_y - tr->ob_y) < 3)
  359.                 {
  360.                     keyobj = obj + 1;
  361.                     txtp = _get_text(tree, keyobj, &txtp2, &tlen);
  362.                 }
  363.             }
  364.         }
  365.         if(tr->ob_flags & DEFAULT)
  366.             priv = TRUE;
  367.         if(tlen)
  368.         {
  369.             if(in)
  370.             {
  371.                 if(!(magic && (undo_obj ? (tree[undo_obj].ob_type & SPECIAL) : FALSE)))
  372.                 {
  373.                     if(_is_spec(undos, MAXUNDO, txtp2))
  374.                     {
  375.                         priv = TRUE;
  376.                         undo_obj = obj;
  377.                     }
  378.                 }
  379.                 if(_is_spec(helps, MAXHELP, txtp2))
  380.                     help_obj = obj;
  381. /*                if(_is_spec(oks, MAXOK, txtp2))
  382.                     priv = TRUE;
  383. */                if(priv)    /* take 1st letter */
  384.                 {
  385.                     pos = _conv_ch(txtp2[0]);
  386.                     savobj = _inskeytab(pos, obj, keyobj, (WORD)(&txtp2[0] - txtp), tlen);
  387.                     if(savobj)
  388.                         _ins_key(tree, savobj, FALSE);
  389.                     goto leave;
  390.                 }
  391.                 if((txtp[0] >= '\x01') && (txtp[0] <= '\x04'))
  392.                 {
  393.                     kt = &keytable[MAXALPH+MAXFKEY+txtp[0]-0x01];
  394.                         kt->obj = obj;
  395.                         kt->kobj = 0;
  396.                         goto leave;
  397.                 }
  398.             }
  399.             i = 0;
  400.             while(txtp2[i])        /* check words */
  401.             {
  402.                 if(isalnum(txtp2[i]))
  403.                 {
  404.                     pos = _conv_ch(txtp2[i]);
  405.                     if(pos != -1)
  406.                     {
  407.                         if(!keytable[pos].obj)
  408.                         {
  409.                             _inskeytab(pos, obj, keyobj, (WORD)(&txtp2[i] - txtp), tlen);
  410.                             goto leave;
  411.                         }
  412.                     }
  413.                 }
  414.                 while(isalnum(txtp2[i]))
  415.                     i++;
  416.                 while(txtp2[i] && !isalnum(txtp2[i]))
  417.                     i++;
  418.             }
  419.             for(i = 0; txtp2[i]; i++)
  420.             {
  421.                 pos = _conv_ch(txtp2[i]);
  422.                 if(pos != -1)
  423.                 {
  424.                     if(!keytable[pos].obj)
  425.                     {
  426.                         _inskeytab(pos, obj, keyobj, (WORD)(&txtp2[i] - txtp), tlen);
  427.                         goto leave;
  428.                     }
  429.                 }
  430.             }
  431.         }
  432. leave:    ;
  433.     }
  434. }
  435.  
  436. /* ----- underline key object ---------------------------------------------- */
  437.  
  438. MLOCAL VOID _und_key(tree, ktab, obj, mode)
  439. OBJECT    *tree;
  440. KBDTAB    *ktab;
  441. WORD    obj,
  442.     mode;
  443. {
  444.     REG WORD    kobj,
  445.             typ,
  446.             just;
  447.     WORD    wchar, hchar;
  448.     WORD    bcol, ucol, patt, fsize;
  449.     WORD    isuser;
  450.     WORD    d;
  451.     CHAR    ch[2];
  452.     CHAR    *tp;
  453.     GRECT    gr;
  454.     VRECT    vr;
  455.     KBDTAB    *kt;
  456.     OBJECT    *tr;
  457.     OBSPEC    *obspc;
  458.  
  459.     if(obj < MAXALPH)
  460.     {
  461.         isuser = FALSE;
  462.         kt = &ktab[obj];
  463.         kobj = kt->kobj;
  464.         tr = &tree[kobj];
  465.         typ = tr->ob_type & 0xff;
  466.         if(magic && (typ == G_USERDEF) && (tr->ob_type & EXAPPL))
  467.         {
  468.             typ = tr->ob_spec.exapblk->ub_type & 0xff;
  469.             obspc = &tr->ob_spec.exapblk->ub_spec;
  470.             isuser = TRUE;
  471.         }
  472.         else
  473.             obspc = (tr->ob_flags & INDIRECT) ? &tr->ob_spec.indirect : &tr->ob_spec;
  474.         if(kt->obj)
  475.         {
  476.             obj_xywh(tree, kobj, &gr);
  477.             wchar = gl_wchar;
  478.             hchar = gl_hchar;
  479.             if((typ == G_BUTTON) || (typ == G_BOXCHAR))
  480.                 just = isuser ? TE_RIGHT : TE_CNTR;
  481.             else if(typ == G_STRING)
  482.                 just = isuser ? TE_RIGHT : TE_LEFT;
  483.             else
  484.             {
  485.                 just = obspc->tedinfo->te_just;
  486.                 if(obspc->tedinfo->te_font == SMALL)
  487.                     wchar = hchar = 6;
  488.             }
  489.             switch(just)
  490.             {
  491.                 case TE_LEFT  :    vr.v_x1 = 0;
  492.                         break;
  493.                 case TE_RIGHT :    vr.v_x1 = gr.g_w - kt->tlen * wchar;
  494.                         break;
  495.                 case TE_CNTR  :    vr.v_x1 = (gr.g_w - kt->tlen * wchar + 1) / 2;
  496.             }
  497.             vr.v_x1 += gr.g_x + kt->chpos * wchar;
  498.             vr.v_y1 = gr.g_y + (gr.g_h - hchar) / 2 + hchar - 1;
  499.             if((AESVersion() >= 0x0340) && !magx
  500.                 && ((((tr->ob_flags & 0x0600) == 0x0600) && (act_mode == 1))
  501.                 || (((tr->ob_flags & 0x0600) == 0x0200) && (ind_mode == 1))))
  502.             {
  503.                 vr.v_y1--;
  504.                 vr.v_x1--;
  505.             }
  506.             vr.v_x2 = vr.v_x1 + wchar - 1;
  507.             vr.v_y2 = vr.v_y1;
  508.             switch(typ)
  509.             {
  510.                 case G_TEXT       :
  511.                 case G_BOXTEXT    :
  512.                 case G_FTEXT      :
  513.                 case G_FBOXTEXT   :    bcol = obspc->tedinfo->te_color & 0x0f;
  514.                             patt = (obspc->tedinfo->te_color & 0x70) >> 4;
  515.                             fsize = obspc->tedinfo->te_font;
  516.                             break;
  517.                 case G_BOXCHAR    : bcol = obspc->obspec.interiorcol;
  518.                             patt = obspc->obspec.fillpattern;
  519.                             fsize = IBM;
  520.                             break;
  521.                 default           :    bcol = 0;
  522.                             patt = 0;
  523.                             fsize = IBM;
  524.                             break;
  525.             }
  526.             ucol = letemfly.ucol & 0xff;
  527.             if(ucol >= colors)
  528.                 ucol = 1;
  529.             if(bcol >= colors)
  530.                 bcol = 1;
  531.             if((tr->ob_state & SELECTED) && !isuser)
  532.             {
  533.                 bcol ^= 0x01;
  534.                 ucol ^= 0x01;
  535.             }
  536.             if((patt > 3) && (ucol == bcol))
  537.                 ucol ^= 0x01;
  538.             if((letemfly.ucol & 0x100) && (colors > 2))
  539.             {
  540.                 if(mode)
  541.                 {
  542.                     tp = _get_text(tree, kobj, NULL, NULL);
  543.                     ch[0] = tp[kt->chpos];
  544.                     ch[1] = '\0';
  545.                     if(fsize == IBM)
  546.                         vst_height(vwk_handle, sysfont, &d, &d, &d, &d);
  547.                     else
  548.                         vst_height(vwk_handle, 4, &d, &d, &d, &d);
  549.                     vst_color(vwk_handle, ucol);
  550.                     vst_alignment(vwk_handle, TE_LEFT, 3, &d, &d);
  551.                     vswr_mode(vwk_handle, MD_TRANS);
  552.                     vs_clip(vwk_handle, 0, (WORD *)&vr);
  553.                     v_gtext(vwk_handle, vr.v_x1, vr.v_y1, ch);
  554.                 }
  555.                 else
  556.                 {
  557. /*                    obj_xywh(tree, kobj, &gr);
  558. */                    vr.v_y1 -= (hchar + 1);
  559.                     rc_vtog(&vr, &gr);
  560.                     objc_draw(tree, ROOT, MAX_DEPTH, gr.g_x, gr.g_y, gr.g_w, gr.g_h);
  561.                 }
  562.             }
  563.             else
  564.             {
  565.                 vsl_color(vwk_handle, mode ? ucol : bcol);
  566.                 v_pline(vwk_handle, 2, &vr);
  567.             }
  568.         }
  569.     }
  570. }
  571.  
  572. VOID _und_obj(tree, ktab, obj, mode)
  573. OBJECT    *tree;
  574. KBDTAB    *ktab;
  575. WORD    obj,
  576.     mode;
  577. {
  578.     REG WORD    i;
  579.     VRECT    vr;
  580.  
  581.     if((lastdone == tree) && keys)    /* && in_do */
  582.     {
  583.         for(i = 0; i < MAXALPH; i++)
  584.         {
  585.             if(keytable[i].obj == obj)
  586.             {
  587.                 graf_mouse(M_OFF, 0l);
  588.                 vwk_handle = vwk_init();
  589.                 vswr_mode(vwk_handle, MD_REPLACE);
  590.                 rc_gtov(&wi_max, &vr);
  591.                 vs_clip(vwk_handle, 0, &vr);
  592.                 _und_key(tree, ktab, i, mode);
  593.                 vwk_exit(vwk_handle);
  594.                 graf_mouse(M_ON, 0l);
  595.                 break;
  596.             }
  597.         }
  598.     }
  599. }
  600.  
  601. /* ----- lookup key object ------------------------------------------------- */
  602.  
  603. WORD STDARGS lookup_key(key, status)
  604. WORD    key,
  605.     status;
  606. {
  607.     WORD    x, y, w, h,
  608.         exit_obj;
  609.     KEYTAB    *ktab;
  610.  
  611.     key = (key >> 8) & 0xff;
  612.     if((status & 0x03) && (key == 98) && !isalert)    /* Info Key */
  613.     {
  614.         isalert = TRUE;
  615.         _dialval(DSAVE);
  616.         nfm_center(info_dial, &x, &y, &w, &h);
  617.         nfm_dial(FMD_START, 0, 0, 0, 0, x, y, w, h);
  618.         objc_draw(info_dial, ROOT, MAX_DEPTH, x, y, w, h);
  619.         exit_obj = nfm_do(info_dial, 0) & 0x7fff;
  620.         nfm_dial(FMD_FINISH, 0, 0, 0, 0, x, y, w, h);
  621.         info_dial[exit_obj].ob_state &= ~SELECTED;
  622.         _dialval(DRESTORE);
  623.         isalert = FALSE;
  624.         return(0);
  625.     }
  626.     if(keys)
  627.     {
  628.         if(key == 97)    /* UNDO Key */
  629.             return(undo_obj);
  630.         if(key == 98)    /* HELP Key */
  631.             return(help_obj);
  632.         if(!ed_flag)
  633.         {
  634.             switch(key)
  635.             {
  636.                 case 72 :    /* Csr Up */
  637.                     return(keytable[MAXALPH+MAXFKEY].obj);
  638.                 case 80 :    /* Crs Down */
  639.                     return(keytable[MAXALPH+MAXFKEY+1].obj);
  640.                 case 77 :    /* Crs Right */
  641.                     return(keytable[MAXALPH+MAXFKEY+2].obj);
  642.                 case 75 :    /* Crs Left */
  643.                     return(keytable[MAXALPH+MAXFKEY+3].obj);
  644.             }
  645.         }
  646.         if((key >= 59) && (key <= 68))    /* F-Key */
  647.             return(keytable[key+MAXALPH-59].obj);
  648.         if((status & 0x08) || !ed_flag)    /* ALT Key / Alerts */
  649.         {
  650.             ktab = Keytbl((VOID *)-1l, (VOID *)-1l, (VOID *)-1l);
  651.             if((key >= 120) && (key <= 129))
  652.                 key = (key == 129) ? 0 : (key - 119);
  653. /*            else if((key >= 1) && (key <= 11))
  654.                 key--;
  655. */            else
  656.             {
  657.                 key = _conv_ch(ktab->capslock[key]);
  658.                 if(key == -1)
  659.                     return(0);
  660.             }
  661.             return(keytable[key].obj);
  662.         }
  663.     }
  664.     return(0);
  665. }
  666.  
  667. /* ----- find key object --------------------------------------------------- */
  668.  
  669. MLOCAL WORD _find_kobj(tree, obj)
  670. OBJECT    *tree;
  671. WORD    obj;
  672. {
  673.     WORD    i;
  674.  
  675.     if(keys && (obj != 0))
  676.     {
  677.         for(i = 0; i < MAXALPH; i++)
  678.         {
  679.             if(keytable[i].kobj == obj)
  680.                 return((tree[keytable[i].kobj].ob_flags & EDITABLE) ? obj : keytable[i].obj);
  681.         }
  682.     }
  683.     return(obj);
  684. }
  685.  
  686. /* ----- calculate position within EDITABLE objects ------------------------ */
  687.  
  688. MLOCAL WORD _getcpos(tree, obj, x)
  689. OBJECT    *tree;
  690. WORD    obj,
  691.     x;
  692. {
  693.     REG WORD    i,
  694.             mpos;
  695.     WORD    slen,
  696.         mlen,
  697.         typ;
  698.     CHAR    *tmask,
  699.         *text;
  700.     GRECT    gr;
  701.     OBJECT    *tr;
  702.     OBSPEC    *obspc;
  703.  
  704.     mpos = -1;
  705.     tr = &tree[obj];
  706.     typ = tr->ob_type;
  707.     if(magic && (typ == G_USERDEF) && (tr->ob_type & EXAPPL))
  708.     {
  709.         typ = tr->ob_spec.exapblk->ub_type & 0xff;
  710.         obspc = &tr->ob_spec.exapblk->ub_spec;
  711.     }
  712.     else
  713.         obspc = (tr->ob_flags & INDIRECT) ? &tr->ob_spec.indirect : &tr->ob_spec;
  714.     text = obspc->tedinfo->te_ptext;
  715.     if(text[0] != '@')
  716.     {
  717.         tmask = obspc->tedinfo->te_ptmplt;
  718.         slen = (WORD)strlen(text);
  719.         mlen = (WORD)strlen(tmask) * gl_wchar;
  720.         obj_xywh(tree, obj, &gr);
  721.         switch(obspc->tedinfo->te_just)
  722.         {
  723.             case TE_RIGHT :    gr.g_x += gr.g_w - mlen;
  724.                     break;
  725.             case TE_CNTR  :    gr.g_x += (gr.g_w - mlen) / 2;
  726.         }
  727.         x -= gl_wchar / 2;
  728.         i = -1;
  729.         do
  730.         {
  731.             i++;
  732.             while((tmask[i] != '_') && tmask[i])
  733.                 i++;
  734.             mpos++;
  735.         }
  736.         while(((gr.g_x + i * gl_wchar) < x) && (mpos <= slen) && tmask[i]);
  737.         if(mpos > slen)
  738.             mpos = slen;
  739.     }
  740.     if(mpos < 0)
  741.         mpos = 0;
  742.     return(mpos);
  743. }
  744.  
  745. /* ----- little treewalk to scan objects ----------------------------------- */
  746.  
  747. MLOCAL VOID _tw(tree, start)
  748. OBJECT    *tree;
  749. WORD    start;
  750. {
  751.     REG WORD    obj,
  752.             flag;
  753.     OBJECT    *tr;
  754.  
  755.     for(obj = tree[start].ob_head; (obj != start) && (obj != -1); obj = tree[obj].ob_next)
  756.     {
  757.         tr = &tree[obj];
  758.         flag = tr->ob_flags;
  759.         if(!ed_flag && (flag & EDITABLE))
  760.             ed_flag = TRUE;
  761.         if((flag & (SELECTABLE|TOUCHEXIT|EXIT)) 
  762.             && !(flag & HIDETREE)
  763.             && !(magic && (flag & KEYDIAL))
  764.             && !(tr->ob_state & (DISABLED|0xff00))
  765.             && ((tr->ob_type & 0xff00) != GLOBOFF))
  766.             _ins_key(tree, obj, TRUE);
  767.         if(!(flag & HIDETREE) && !(magic && (flag & KEYDIAL)))
  768.             _tw(tree, obj);
  769.     }
  770. }
  771.  
  772. /* ----- initilialize keys ------------------------------------------------- */
  773.  
  774. WORD STDARGS init_keys(tree)
  775. OBJECT    *tree;
  776. {
  777.     REG WORD    i;
  778.     VRECT    vr;
  779.  
  780.     if(!initflag)
  781.         ltmf_init();
  782.     magic = ((UWORD)(tree[ROOT].ob_type & 0xff00) == MAGIC) ? TRUE : FALSE;
  783.     keys = ((letemfly.conf & C_KEYS) && !(magic && (tree[ROOT].ob_flags & KEYDIAL))) ? TRUE : FALSE;
  784.     ed_flag = FALSE;
  785.     if(tree != lastdone)
  786.     {
  787.         for(i = 0; i < MAXKEYS; i++)
  788.         {
  789.             oldkbtab[i].obj = 0;
  790.             oldkbtab[i].kobj = 0;
  791.         }
  792.     }
  793.     if(keys)
  794.     {
  795.         for(i = 0; i < MAXKEYS; i++)
  796.         {
  797.             keytable[i].obj = 0;
  798.             keytable[i].kobj = 0;
  799.         }
  800.         undo_obj = help_obj = 0;
  801.         _tw(tree, ROOT);
  802.         if(letemfly.ucol & 0xff)
  803.         {
  804.             vwk_handle = vwk_init();
  805. /*            vsl_type(vwk_handle, 1);
  806. */            vsl_width(vwk_handle, 1);
  807.             vswr_mode(vwk_handle, MD_REPLACE);
  808.             rc_gtov(&wi_max, &vr);
  809.             vs_clip(vwk_handle, 0, &vr);
  810.             graf_mouse(M_OFF, 0l);
  811.             for(i = 0; i < MAXALPH; i++)
  812.             {
  813.                 if((lastdone == tree) && memcmp(&oldkbtab[i], &keytable[i], sizeof(KBDTAB)))
  814.                     _und_key(tree, oldkbtab, i, 0);
  815.             }
  816.             for(i = 0; i < MAXALPH; i++)
  817.                 _und_key(tree, keytable, i, 1);
  818.             graf_mouse(M_ON, 0l);
  819.             vwk_exit(vwk_handle);
  820.         }
  821.         memcpy(oldkbtab, keytable, sizeof(KBDTAB) * MAXKEYS);
  822.     }
  823.     lasttree = NULL;
  824.     lastdone = tree;
  825.     return(keys);
  826. }
  827.  
  828. /* ----- initialize dialog ------------------------------------------------- */
  829.  
  830. MLOCAL WORD _init_fm(tree, startobj)
  831. OBJECT    *tree;
  832. WORD    startobj;
  833. {
  834.     REG WORD    obj;
  835.     WORD    next_obj,
  836.         edflag;
  837.     WORD    x, y, w, h;
  838.     OBJECT     *tr;
  839.  
  840.     /* obj = */ next_obj = fly_obj = 0;
  841.     obj = -1;
  842.     edflag = TRUE;
  843.     do
  844.     {
  845.         tr = &tree[++obj];
  846.         if(((tr->ob_type & 0xff00) != GLOBOFF) && magic && (tr->ob_type & FLYER))
  847.         {
  848.             if(!(tr->ob_type & FLYALL))
  849.                 fly_obj = obj;
  850.             if(!di_moveto(tree, -1, 0) && !(tr->ob_type & FLYNOCL))
  851.             {
  852.                 tr->ob_flags |= HIDETREE;
  853.                 obj_clsize(tree, obj, &x, &y, &w, &h);
  854.                 objc_draw(tree, ROOT, MAX_DEPTH, x, y, w, h);
  855.                 tr->ob_flags &= ~HIDETREE;
  856.             }
  857.         }
  858.         if(edflag && (tr->ob_flags & EDITABLE))
  859.         {
  860.             next_obj = obj;
  861.             edflag = FALSE;
  862.         }
  863.     }
  864.     while(!(tr->ob_flags & LASTOB));
  865.     if(startobj > 0)
  866.         next_obj = startobj;
  867.     return(next_obj);
  868. }
  869.  
  870. /* ------------------------------------------------------------------------- */
  871. /* ----- new form_do() ----------------------------------------------------- */
  872. /* ------------------------------------------------------------------------- */
  873.  
  874. WORD nfm_do(tree, startobj)
  875. OBJECT    *tree;
  876. WORD    startobj;
  877. {
  878.     WORD    edit_obj,
  879.         next_obj,
  880.         last_obj,
  881.         kb_obj,
  882.         obj, csr,
  883.         eat_key,
  884.         event,
  885.         idx,
  886.         mx, my, mbut,
  887.         ks, kr, br,
  888.         cont,
  889.         cflag;
  890.     WORD    i, d;
  891.  
  892.     in_do = TRUE;
  893.     mx = 0;
  894.     cont = TRUE;
  895.     cflag = FALSE;
  896.     edit_obj = 0;
  897.     last_obj = -2;
  898.     idx = 0;
  899.  
  900.     if((tree[ROOT].ob_type & 0xff00) == GLOBOFF)
  901.         return(form_do(tree, startobj));
  902.     wind_update(BEG_UPDATE);
  903.     wind_update(BEG_MCTRL);
  904.     do
  905.     {
  906.         event = evnt_multi(MU_KEYBD|MU_TIMER, 0x02, 0x01, 0x01,
  907.                     0, 0, 0, 0, 0,
  908.                     0, 0, 0, 0, 0,
  909.                     0l, 0, 0,
  910.                     &d, &d, &d, &d, &d, &d);
  911.     }
  912.     while(event & MU_KEYBD);
  913.     init_keys(tree);
  914.     next_obj = _init_fm(tree, startobj);
  915.     graf_mkstate(&mx, &my, &mbut, &ks);
  916.     obj = objc_find(tree, ROOT, MAX_DEPTH, mx, my);
  917.     if((obj != -1) && (tree[obj].ob_flags & EDITABLE))
  918.         csr = TEXT_CRSR;
  919.     else
  920.         csr = ARROW;
  921.     graf_mouse(csr, 0L);
  922.     while(cont)
  923.     {
  924.         if(next_obj && (edit_obj != next_obj))
  925.         {
  926.             edit_obj = next_obj;
  927.             next_obj = 0;
  928.             nob_edit(tree, edit_obj, 0, &idx, ED_INIT);
  929.             if(cflag)
  930.                 nob_edit(tree, edit_obj, 0, &idx, ED_END);
  931.         }
  932.         if(cflag)
  933.         {
  934.             idx = _getcpos(tree, edit_obj, mx);
  935.             nob_edit(tree, edit_obj, 0, &idx, ED_END);
  936.             cflag = FALSE;
  937.         }
  938.         event = evnt_multi(MU_KEYBD|MU_BUTTON|MU_M1|MU_TIMER, 0x02, 0x01, 0x01,
  939.                     1, mx, my, 1, 1,
  940.                     0, 0, 0, 0, 0,
  941.                     0l, 200, 0,
  942.                     &mx, &my, &mbut, &ks, &kr, &br);
  943.         if(event & MU_KEYBD)
  944.         {
  945.             eat_key = (!isalert && letemfly.do_key) ? letemfly.do_key(kr, ks) : FALSE;
  946.             if(!eat_key)
  947.             {
  948.                 kb_obj = lookup_key(kr, ks);
  949.                 if(kb_obj)
  950.                     cont = nfm_button(tree, kb_obj, 0x01, &next_obj);
  951.                 else
  952.                 {
  953.                     cont = nfm_keybd(tree, edit_obj, next_obj, kr, &next_obj, &kr);
  954.                     if(kr)
  955.                         nob_edit(tree, edit_obj, kr, &idx, ED_CHAR);
  956.                 }
  957.             }
  958.             else if(eat_key == 2)
  959.             {
  960.                 cont = FALSE;
  961.                 next_obj = 0;
  962.             }
  963.         }
  964.         if(event & MU_BUTTON)
  965.         {
  966.             next_obj = _find_kobj(tree, objc_find(tree, ROOT, MAX_DEPTH, mx, my));
  967.             i = 0;
  968.             while((((letemfly.conf & C_JUMP) && (next_obj == -1))
  969.                 || ((next_obj != -1) && ((tree[next_obj].ob_flags & 0xdf) == NONE) && !fly_obj))
  970.                 && (i++ < letemfly.flydelay) && (mbut == 0x01))
  971.             {
  972.                 evnt_timer(10, 0);
  973.                 graf_mkstate(&mx, &my, &mbut, &ks);
  974.                 next_obj = objc_find(tree, ROOT, MAX_DEPTH, mx, my);
  975.             }
  976.             if(next_obj == -1)
  977.             {
  978.                 if((last_obj >= 0) || ((last_obj < 0) && !di_moveto(tree, mx, my)))
  979.                     Bconout(2, 7);
  980.                 next_obj = 0;
  981.             }
  982.             else if(fly_obj && (next_obj == fly_obj) && (mbut != 0x03))
  983.             {
  984.                 if(br == 2)
  985.                     di_center(tree);
  986.                 else
  987.                     di_fly(tree);
  988.                 last_obj = next_obj;
  989.                 next_obj = 0;
  990.             }
  991.             else if(((tree[next_obj].ob_flags & 0xdf) == NONE) && (!fly_obj || (mbut == 0x03)))
  992.             {
  993.                 if(br == 2)
  994.                     di_center(tree);
  995.                 else
  996.                     di_fly(tree);
  997.                 last_obj = next_obj;
  998.                 next_obj = 0;
  999.             }
  1000.             else
  1001.             {
  1002.                 last_obj = next_obj;
  1003.                 cont = nfm_button(tree, next_obj, br, &next_obj);
  1004.             }
  1005.             if((tree[next_obj & 0x7fff].ob_flags & EDITABLE) && (letemfly.conf & C_EDIT))
  1006.                 cflag = TRUE;
  1007.         }
  1008.         else if(event & MU_TIMER)
  1009.             last_obj = -2;
  1010.         if(event & MU_M1)
  1011.         {
  1012.             obj = objc_find(tree, ROOT, MAX_DEPTH, mx, my);
  1013.             if((obj != -1) && (tree[obj].ob_flags & EDITABLE))
  1014.             {
  1015.                 if(csr != TEXT_CRSR)
  1016.                 {
  1017.                     csr = TEXT_CRSR;
  1018.                     graf_mouse(csr, 0L);
  1019.                 }
  1020.             }
  1021.             else if(csr != ARROW)
  1022.             {
  1023.                 csr = ARROW;
  1024.                 graf_mouse(csr, 0L);
  1025.             }
  1026.         }
  1027.         if((!cont) || cflag || (next_obj && (next_obj != edit_obj)))
  1028.             nob_edit(tree, edit_obj, 0, &idx, ED_END);
  1029.     }
  1030.     wind_update(END_MCTRL);
  1031.     wind_update(END_UPDATE);
  1032.     graf_mouse(ARROW, 0L);
  1033.     in_do = FALSE;
  1034.     ed_flag = TRUE;
  1035.     return(next_obj);
  1036. }
  1037.